
//创建文件：etherdata.js
//合约地址：0x80ea94bf5078a8b3dda270e9044a6e714c3fa008

var Web3 = require('web3');           //引用web3模块
var fs = require('fs');               //node模块（内置的，不需安装），用来操作文件
var Tx = require('ethereumjs-tx');    //引用账户的私钥用来为数据签名的模块
//import ethabi from 'web3-eth-abi'; //用来解码
var ethabi = require('web3-eth-abi');
//问题：有可能是express框架不支持es6的import导入

class EtherData {
    /*
    * 核心业务：四个方法
    * addNote                 添加笔记
    * updateNote              修改/更新笔记
    * getNote                 查询笔记
    * queryTransactionStaus   交易状态
    *
    * */

    //①先在构造函数进行初始化
    constructor() {
        //设置CloudNoteService的合约地址
        this.contractAddress = '0xfdf0504b07a21167f1c9d67468838cd8d5f5def4';

        //设置Gas单价为1GWei(十六进制表示)
        this.gasPrice = '0x3B9ACA00';

        //连接以太坊节点,
        // ①如果智能合约是发布到以太虚拟网络上就可以申请一个节点去连接，以太坊网络会提供（申请地址：https://infura.io/signup）
        // ②我们这里直接发布到本地的以太坊虚拟网络，直接连接到本地主机上
        this.web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:7545'));

        //加载接口文件（转成字符串）
        this.abi = JSON.parse(fs.readFileSync('routes/CloudNoteService_sol_CloudNoteService.abi').toString());

        //指定合约地址，绑定实例化的合约对象
        this.contract = this.web3.eth.contract(this.abi).at(this.contractAddress);

        // this.contract = new web3.eth.Contract(this.abi[this.contractAddress]);
        //console.log('输出:',this.contract)

    }

    //直接获取以太坊的交易数nonce
    getNonce() {
        var nonce = this.web3.eth.getTransactionCount("0xDe509107433a93cadf6e4F568EaB6760a3E4d989");
        return nonce;
    }

    //添加更新云笔记
    addUpdateNote(id, name, content, notefun) {
        //获取预估Gas消耗值
        var estimateGas = this.web3.eth.estimateGas({
            to: this.contractAddress,
            data: notefun
        })


        //每次交易提交一个对象，防止攻击网络
        var nonce = global.getNextNonce();
        var rawTx = {
            nonce: nonce,   //nonce值，每笔交易加1
            gasPrice: this.gasPrice,  //Gas单价
            gasLimit: estimateGas,   //发布交易预估消耗的Gas值
            to: this.contractAddress,  //指向合约地址
            value: "0x00",  //交易值
            data: notefun
        }
        //开始用私有key来签名
        var tx = new Tx.Transaction(rawTx);
        //设置账户的私钥
        const privateKey = new Buffer('9299ba7943fa77a104ac29c161003e5353bb1e3335c2aa4c132e109c45f2fd6b', 'hex');//十六进制，放进Buffer对象
        //签名
        tx.sign(privateKey);
        //序列化
        var serializedTx = tx.serialize();
        //返回交易地址
        return this.web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'));
    }

    //添加云笔记
    addNote(id, name, content) {
        // var addNote = this.contract.addNote.getData(id,name,content);
        // //获取预估Gas消耗值
        // var estimateGas = this.web3.eth.estimateGas({
        //     to:this.contractAddress,
        //     data:addNote
        // })
        //
        //
        // //每次交易提交一个对象，防止攻击网络
        // var nonce = global.getNextNonce();
        // var rawTx = {
        //     nonce:nonce,   //nonce值，每笔交易加1
        //     gasPrice:this.gasPrice,  //Gas单价
        //     gasLimit:estimateGas,   //发布交易预估消耗的Gas值
        //     to:this.contractAddress,  //指向合约地址
        //     value:"0x00",  //交易值
        //     data:addNote
        // }
        // //开始用私有key来签名
        // var tx = new Tx(rawTx);
        // //设置账户的私钥
        // const privateKey = new Buffer('623e0083cf26a5d9da7a5f3264bd12672d749d1ab896de9712a5693c3637982c','hex');//十六进制，放进Buffer对象
        // //签名
        // tx.sign(privateKey);
        // //序列化
        // var serializedTx = tx.serialize();
        // //返回交易地址
        // return this.web3.eth.sendRawTransaction('0x'+serializedTx.toString('hex'));

        var addNote = this.contract.addNote.getData(id, name, content);
        return this.addUpdateNote(id, name, content, addNote);
    }

    //更新云笔记
    updateNote(id, name, content) {
        var updateNote = this.contract.updateNote.getData(id, name, content);
        return this.addUpdateNote(id, name, content, updateNote);
    }

    //根据用户ID和笔记名称获取笔记内容
    getNote(id, name) {
        //需要一个对象的地址（合约地址）
        //首先需要保存二进制数据
        //getNote这是合约里面的接口
        //getData直接调用接口的数据
        var getNote = this.contract.getNote.getData(id, name);
        //测试1
        // console.log(getNote);
        //通过call方法来调用
        var result = this.web3.eth.call({
            to: this.contractAddress,     //指定到调用合约的地址
            data: getNote
        });
        // console.log('大开口说：', result);
        return ethabi.decodeParameter('string', result);
    }

    //删除笔记
    deleteNote(id, name){
        return this.contract.deleteNote.getData(id,name);
    }

    //返回交易状态，1：成功，0：失败  null：未处理
    queryTransactionStatus(hash) {
        //获取交易数据
        var result = this.web3.eth.getTransactionReceipt(hash);
        if (result != null) {
            return parseInt(result.status, 16);
        }
        return null;
    }

}

module.exports = EtherData;
